package com.zh.baselibrary.utils;


import android.text.TextUtils;

import com.github.stuxuhai.jpinyin.PinyinException;
import com.github.stuxuhai.jpinyin.PinyinFormat;
import com.github.stuxuhai.jpinyin.PinyinHelper;

import java.lang.reflect.Field;
import java.util.Comparator;
import java.util.List;

@SuppressWarnings("rawtypes")
public class ComparatorUtils implements Comparator {
    //要排序的属性名
    private String name;
    private String childName;
    //是否升序
    private boolean flag = true;
    //拼音排序
    private boolean isLetter = false;

    /**
     * @param childName 属性类的get方法
     * @param name      要排序的属性名,如果是基本类型的排序，请入null值
     * @param flag      false/true : 升序/降序
     */
    public ComparatorUtils(String childName, String name, boolean flag) {
        super();
        this.childName = childName;
        this.name = name;
        this.flag = flag;
    }
    public ComparatorUtils(String childName, String name, boolean flag, boolean isLetter) {
        super();
        this.childName = childName;
        this.name = name;
        this.flag = flag;
        this.isLetter = isLetter;
    }

    @Override
    public int compare(Object o1, Object o2) {
        int result = 0;
        //入参为空|参数类型不相等，都不进行处理。
        if (o1 == null || o2 == null || !o1.getClass().getName().equals(o2.getClass().getName())) {
            return result;
        }
        //7大基本类型的处理(boolean除外.且把Collections.reverse()/Collections.sort()的事也做了)
        if (isBaseType(o1)) {
            //比较
            return baseTypeOpt(o1, o2);
        }
        try {
            Field f1 = o1.getClass().getDeclaredField(name);
            Field f2 = o2.getClass().getDeclaredField(name);
            //设置private可读
            f1.setAccessible(true);
            f2.setAccessible(true);
            result = baseTypeOpt(f1.get(o1), f2.get(o2));
            f1.setAccessible(false);
            f2.setAccessible(false);
        } catch (NoSuchFieldException e) { //如果没有对应的属性,找属性类中
            if (!TextUtils.isEmpty(childName)) {
                try {
                    Object child1 = o1.getClass().getMethod(childName).invoke(o1);
                    Class clazz1 = child1.getClass();
                    Object child2 = o2.getClass().getMethod(childName).invoke(o2);
                    Class clazz2 = child2.getClass();
                    Field f1 = clazz1.getDeclaredField(name);
                    Field f2 = clazz2.getDeclaredField(name);
                    //设置private可读
                    f1.setAccessible(true);
                    f2.setAccessible(true);
                    result = baseTypeOpt(f1.get(child1), f2.get(child2));
                    f1.setAccessible(false);
                    f2.setAccessible(false);
                } catch (Exception e1) {
                    e1.printStackTrace();
                    LogUtils.e(e1.getMessage());
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return result;
    }

    private int baseTypeOpt(Object o1, Object o2) {
        int result = 0;
        if (o1 instanceof String) {
            if(isLetter){
                try {
                    String name1 =  PinyinHelper.getShortPinyin((String) o1);
                    String name2 =  PinyinHelper.getShortPinyin((String) o2);
                    if(TextUtils.isEmpty(name1)||TextUtils.isEmpty(name2)){
                        return  -1;
                    }else {
                        for(int i = 0;i<name1.length();i++){
                            if(name2.length()<=i)
                                return  1;
                            char a = name1.charAt(i);
                            char b = name2.charAt(i);
                            if (a - b > 0) {
                                result = 1;
                                break;
                            } else if (a - b < 0) {
                                result = -1;
                                break;
                            }
                        }
                    }
                } catch (PinyinException e) {
                    e.printStackTrace();
                }

            }else {
                    if ((((String) o1).length() - (((String) o2).length())) > 0) {
                        result = 1;
                    } else if ((((String) o1).length() - (((String) o2).length())) < 0) {
                        result = -1;
                    }
            }
        } else if (o1 instanceof Integer) {
            result = ((Integer) o1) - ((Integer) o2);
        } else if (o1 instanceof Double) {
            if (((Double) o1 - (Double) o2) > 0) {
                result = 1;
            } else if (((Double) o1 - (Double) o2) < 0) {
                result = -1;
            }
        } else if (o1 instanceof Float) {
            if (((Float) o1 - (Float) o2) > 0) {
                result = 1;
            } else if (((Float) o1 - (Float) o2) < 0) {
                result = -1;
            }
        } else if (o1 instanceof Character) {
            result = ((Character) o1).compareTo(((Character) o2));
        } else if (o1 instanceof Short) {
            result = ((Short) o1) - ((Short) o2);
        } else if (o1 instanceof Long) {
            if (((Long) o1 - (Long) o2) > 0) {
                result = 1;
            } else if (((Long) o1 - (Long) o2) < 0) {
                result = -1;
            }
        } else if (o1 instanceof List) {
            if (((List) o1).size() - ((List) o2).size() > 0)
                result = 1;
            else if (((List) o1).size() - ((List) o2).size() < 0) {
                result = -1;
            }

        }
        //降序
        if (!isflag()) {
            result = -result;
        }
        return result;
    }

    private boolean isBaseType(Object o) {
        if ((o instanceof String) || (o instanceof Integer)
                || (o instanceof Double) || (o instanceof Float)
                || (o instanceof Character) || (o instanceof Short)
                || (o instanceof Long)) {
            return true;
        }
        return false;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isflag() {
        return flag;
    }

    public void setflag(boolean flag) {
        this.flag = flag;
    }

}